import java.io.*;
import java.util.*;

/**Die Main-Klasse, liest einen Binärstring ein, von einer Datei,
 * listet und sortiert den String nach Häufigkeit und speichert
 * diese in einem Baum.
 * 
 * @author Björn Klemm, Gerd Ohlweiler, Anna Macjiewska
 *
 */
public class Aufg2 {
	
	public static LinkedHashMap<String,Integer> map = new LinkedHashMap<String,Integer>();
	/**Startmethode
	 * 
	 * @param args Eingabedatei Ausgabedatei
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		if(args.length != 2)
			errorMsg();
		else {
			String s = "";
			String binfilename = args[0];
			String compressfilename = args[1];
			
			StringBuffer content = new StringBuffer();
			BufferedReader stdin = new BufferedReader(new InputStreamReader(new FileInputStream(binfilename)));
			
			while((s = stdin.readLine()) != null){
				content.append(s);
			}
			stdin.close();
			
			String fin = content.toString();
			int fileLen = fin.length();
			
			String value = "";
			int key = 0, lineCount = 0;
			int t = 0, sum = 0;

			for(int i=0; i < fin.length(); i++){
				if(i % 8 == 0){
					
					value = fin.substring(i, t = i + 8);
					if(map.containsKey(value))
					       map.put(value,new Integer(map.get(value).intValue()+1));
					   else
					       map.put(value,new Integer(1));
					
				}
				lineCount++;
			}

			for(Map.Entry<String,Integer> m:map.entrySet()){
				System.out.println(m.getKey() + " " + m.getValue());
				sum += m.getValue();
			}
			sum /= 2;
			System.out.println(sum);
			

			 /*     Berrechnung des Mittelwerts
			 *     Merke letzten Index und splitte HashMap in 2 Teile
			 * }
			 * 
			 * for(int j=0; j < teilmap.size(); i++){
			 * 	   tree.insertLeft(map.get(i));
			 * }
			 * for(int i=0; i < teilmap2.size(); i++){
			 *     tree.insertRight(map.get(i));
			 * }
			 * 
			 */
			Object[] keys = map.keySet().toArray();
			StringBuilder sb = new StringBuilder();
			MergeSort ms = new MergeSort();
			ms.mergeSort(keys);
			CompressTree tree = new CompressTree();
			
			for(Map.Entry<String,Integer> m:map.entrySet()){
				tree.insert(m.getKey());
				sb.append(m.getKey());
			}
			//int nodesum = tree.getSumOfNodes();
			saveFile(compressfilename,sb.toString(),fileLen);
		}

	}
	/**Methode zum speichern der komprimierten Datei
	 * 
	 * @param filename Name der Speicherdatei
	 * @param content Abbildung + Binärstring komprimiert
	 * @param filelen Länge des String's der Eingabedatei
	 * @throws IOException
	 */
	private static void saveFile(String filename,String content,int filelen) throws IOException{
		File f = new File(filename);
		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f,true)));
		out.write(filelen+"\n"+content);
		out.close();
	}
	/**
	 * Methode zur Parameterfehleingabe
	 */
	private static void errorMsg() {
		System.out.println("Usage:    binsourcefile compressedfile");
		
	}

}
